package hci.drummer;

import java.io.BufferedOutputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import android.util.Log;

import hci.drummer.command.Command;

public class CommandPusher {
	private Queue<Command> commands = new ConcurrentLinkedQueue<Command>();
	private Socket socket;
	private Sender sender;

	public void startSend(Socket s) {
		this.socket = s;
		try {
			this.sender = new Sender(socket.getOutputStream());
			this.sender.start();
			for (int i = 0; i < 100; i++) {
				Command command = new Command(i);
				command.setData(i + 1, i + 2, i + 3);
				this.pushCommand(command);
			}
		} catch (IOException e) {
			e.printStackTrace();
			Log.d("Drummer", "sender failed when start");
			Log.d("Drummer", e.toString());
		}
	}

	public void stopWork() throws IOException {
		if (sender != null && sender.isAlive()) {
			this.sender.stopWork();
		}
	}

	class Sender extends Thread {
		private DataOutputStream dos;
		private volatile boolean stopped = false;

		private Sender(OutputStream out) {
			this.dos = new DataOutputStream(new BufferedOutputStream(out));
		}

		public void stopWork() {
			this.stopped = true;
		}

		public void run() {
			while (!this.stopped) {
				synchronized (commands) {
					while (commands.isEmpty()) {
						try {
							commands.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
							Log.d("Drummer", "interrupted");
						}
					}
					if (!commands.isEmpty())
						send(commands.poll());
				}
			}
		}

		private void send(Command c) {
			try {
				dos.writeInt(c.getType());
				dos.writeDouble(c.getX());
				dos.writeDouble(c.getY());
				dos.writeDouble(c.getZ());
				dos.flush();
			} catch (IOException e) {
				e.printStackTrace();
				Log.d("Drummer", e.toString());
			}
		}
	}

	public void pushCommand(Command command) {
		synchronized (commands) {
			commands.offer(command);
			commands.notify();
		}
	}
}